#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/mman.h>

#include "shmfifo.h"
#include "shmstruct.h"
#include "dataxchgtable.h"


struct l0032_dataxchgtable* __l0032_dxtable = NULL;

void l0032_dataxchgtable_printentry()
{
#if 0
	int i;
	struct l0032_dataxchgtable_entry *entry = NULL;

	printf("============ print dxtaxchgtable start ============== \n");
	printf("nentries:%u, sz:%lu, offset:%u, end:%u \n",	__l0032_dxtable->nentries,
				__l0032_dxtable->sz, __l0032_dxtable->offset_data, __l0032_dxtable->end);
	for (i = 0; i < __l0032_dxtable->nentries;i ++) {
		entry = &__l0032_dxtable->entry[i];
		printf("[%02d]=%0x, offset:%d, pointsz:%lu, points:%lu, datatype:%d, name:%s,  \n", i,L0032_INDEX2HANDLE(i),entry->offset,
			entry->pointsz, entry->npoints,entry->flags, entry->name);
	}
	printf("============ print dxtaxchgtable end ============== \n");
#endif
}

void __l0032_ipc_mutex_lock(pthread_mutex_t *lock)
{
	if (pthread_mutex_lock(lock) == EOWNERDEAD) {
		pthread_mutex_consistent(lock);
	}
}

void __l0032_ipc_mutex_unlock(pthread_mutex_t *lock)
{
	pthread_mutex_unlock(lock);
}

void l0032_dataxchgtable_lock(void)
{
	__l0032_ipc_mutex_lock(&__l0032_dxtable->lock);
}

void l0032_dataxchgtable_unlock(void)
{
	__l0032_ipc_mutex_unlock(&__l0032_dxtable->lock);
}

void l0032_entry_lock(entry_handle hentry)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	int entry_index = L0032_HANDLE2INDEX(hentry);	
	entry = &__l0032_dxtable->entry[entry_index];
	__l0032_ipc_mutex_lock(&entry->lock);
}

void l0032_entry_unlock(entry_handle hentry)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	int entry_index = L0032_HANDLE2INDEX(hentry);	
	entry = &__l0032_dxtable->entry[entry_index];
	__l0032_ipc_mutex_unlock(&entry->lock);
}

int l0032_is_valid_entryhandle(entry_handle hentry)
{
	return L0032_HANDLE2INDEX(hentry) != INVALID_ENTRY_HANDLE || hentry != INVALID_ENTRY_HANDLE || hentry != 0;
}

int __l0032_lock_initialize(void *mutexlock_addr)
{
	int retval = 0;
	pthread_mutexattr_t attr;
	pthread_mutexattr_init(&attr);
	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
	pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
	pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);
	if (pthread_mutex_init(mutexlock_addr, &attr) != 0) {
		printf("Fail to intialize the mutex: %s\n", strerror(errno));
		retval = -1;
	}
	/* release the attr object */
	pthread_mutexattr_destroy(&attr);
	return retval;
}

int __l0032_lock_uninitialize(void *mutexlock_addr)
{
	int retval = 0;
	pthread_mutex_destroy(mutexlock_addr);
	return retval;
}

void * __l0032_shm_initialize(const char* shmname, size_t sz, int iscreated)
{
	int fd_shmtmp = -1;
	int fd_shm = -1;
	void *addr = NULL;

	//*iscreated = 0;
	/* SHM does not exist now! Try create a new one */
	if (iscreated) {
		char shm_filename[64];
		char shm_oldpath[256];
		char shm_newpath[256];
		
		if (fd_shm > 0) {
			close(fd_shm);
			fd_shm = -1;
		}

		snprintf(shm_filename, 256, "%s.%d", shmname, getpid());
		fd_shmtmp = shm_open(shm_filename, O_CREAT | O_RDWR, 0777);
	
		if (fd_shmtmp < 0) {
			printf("Fail to create shm %s\n", shmname);
			goto err1;
		}
		
		if (ftruncate(fd_shmtmp, sz) < 0) {
			goto err2;
		}
	
		addr = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd_shmtmp, SEEK_SET);
		if (addr == NULL) {
			goto err2;
		}
		memset(addr, 0, sz);
	
		/* close the shm */
		munmap(addr, sz);
	
		snprintf(shm_oldpath, 256, "/dev/shm/%s", shm_filename);
		snprintf(shm_newpath, 256, "/dev/shm/%s", shmname);
	
		link(shm_oldpath, shm_newpath);
		unlink(shm_oldpath);

		//*iscreated = 1;
		//printf("++++++++++++++ __l0017_shm_initialize name=%s create \n", shmname);
	}

	fd_shm = shm_open(shmname, O_RDWR, 0777);
	if (fd_shm < 0) {
		printf("Fail to open shm %s:%s\n", shmname, strerror(errno));
		goto err2;
	}

	addr = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd_shm, SEEK_SET);
	if (addr == NULL) {
		printf("Fail to mmap shm %s:%s\n", shmname, strerror(errno));
		goto err2;
	}

	// printf("shm :%s addr:%p, sz:%d-%0x \n",shmname, addr, (int)sz, (unsigned int)sz);
	close(fd_shm);
	//printf("++++++++++++++ __l0017_shm_initialize name=%s open \n", shmname);

	return addr;
err2:
	if (fd_shmtmp != -1)
		close(fd_shmtmp);
	if (fd_shm != -1)
		close(fd_shm);
err1:
	return NULL;
}

entry_handle l0032_dataxchgtable_index2handle(int entry_index)
{
	return L0032_INDEX2HANDLE(entry_index);
}

int l0032_dataxchgtable_handle2index(entry_handle hentry)
{
	return L0032_HANDLE2INDEX(hentry);
}

int l0032_dataxchgtable_open(const char* shmname, size_t *sz, int bCreate)
{
	struct l0032_dataxchgtable* dxtable = NULL;
	// printf("%s shmname %s sz %zu create %d\n", __func__, shmname, *sz, bCreate);
	// printf("sz %zu\n", *sz);
	if (sz == NULL) {
		printf("Missing sz for open dataxchgtable, null is not allow for sz\n");
		goto err1;
	}

	if (*sz == 0) {
		*sz = L0032_DXTABLE_DEFAULT_SIZE;
	}
	if (*sz <= L0032_DXTABLE_METADATA_SIZE) {
		//printf("Invalid sz(%ld)\n", *sz);
		goto err1;
	}
	// printf("sz %zu\n", *sz);
	/* create shared memory */
	if (shmname == NULL) {
		shmname = L0032_DXTABLE_NAME;
	}
	// printf("%s shmname %s sz %zu create %d\n", __func__, shmname, *sz, bCreate);
	// printf("%s: create dxtable shmname %s\n", __func__, shmname);
	if (shmname && strlen(shmname) < L0032_SHM_FILENAME_MAX) {
		dxtable = __l0032_shm_initialize(shmname, *sz, bCreate);
		if (dxtable) {
			if (bCreate) 
			{
				int i;
				dxtable->sz = *sz;
				if (__l0032_lock_initialize(&dxtable->lock) == -1) {
					printf("Fail to initialize mutex lock for metadata in dxtable\n");
					goto err2;
				}
				
				for (i = 0; i < L0032_DXTABLE_ENTRYMAX;i ++) {
					memset(&dxtable->entry[i], 0, sizeof(struct l0032_dataxchgtable_entry));
					dxtable->entry[i].flags = L0032_DXTABLE_FLAGS_UNASSIGNED;
					if (__l0032_lock_initialize(&dxtable->entry[i].lock) == -1) {
						printf("Fail to initialize mutex lock for entry in metadata\n");
						goto err2;
					}
				}
				dxtable->offset_data = L0032_ALIGN(sizeof(struct l0032_dataxchgtable), 32);
				dxtable->end = (uint32_t)*sz;
				dxtable->nentries = 0;
			}
			// printf("dxtable addr:%p, sz:%0x, bCreate %d entries:%d\n", dxtable, (unsigned int)*sz, bCreate, dxtable->nentries);
		}
		else {
			printf("Fail to open shm for dxtable\n");
			goto err2;
		}
	}
/*
	if(resetflag){
		int i = 0;
		printf("resetflag == 1, reset dxt, old entrynum=%d, offset_data:%d \n", dxtable->nentries, dxtable->offset_data);
		for( i = 0; i < dxtable->nentries; i++){
			__l0032_lock_uninitialize(&dxtable->entry[i].lock);
		}
		for (i = 0; i < L0032_DXTABLE_ENTRYMAX;i ++) {
			memset(&dxtable->entry[i], 0, sizeof(struct l0032_dataxchgtable_entry));
			dxtable->entry[i].flags = L0032_DXTABLE_FLAGS_UNASSIGNED;
			if (__l0032_lock_initialize(&dxtable->entry[i].lock) == -1) {
				printf("Fail to initialize mutex lock for entry in metadata\n");
				goto err2;
			}
		}
		dxtable->offset_data = L0032_ALIGN(sizeof(struct l0032_dataxchgtable), 32);
		dxtable->end = (uint32_t)*sz;
		dxtable->nentries = 0;
	}*/
	
	__l0032_dxtable = dxtable;
	return 0;
err2:
	if (dxtable) {
		munmap(dxtable, dxtable->sz);
	}
err1:
	return -1;
}

void l0032_dataxchgtable_close(void)
{
	if (__l0032_dxtable) {
		munmap(__l0032_dxtable, __l0032_dxtable->sz); 	
		__l0032_dxtable = NULL;
	}
}

/* 
 * For the purpose of performance, no much access safety checking here
 */
int l0032_entry_read(entry_handle hentry, int pointno, void* addr, size_t sz) {
	int retval = -1;
	struct l0032_dataxchgtable_entry *entry = NULL;
	int entry_index = L0032_HANDLE2INDEX(hentry);

#define __L0032_DATAXCHGTABLE_ENTRY_READ(TYPE)	do {\
	TYPE *point = (TYPE*)(((uint8_t*)__l0032_dxtable) + entry->offset + pointno * entry->pointsz);\
	memset(addr, 0, sz);\
	memcpy(addr, point, sizeof(TYPE));\
	retval = sizeof(TYPE);\
	/*printf("r-%s:[%x] val %d\n",  #TYPE, (unsigned int)(entry->offset + pointno * entry->pointsz), (int)(*point));*/} while(0)

	if (addr != NULL && sz > 0) {
		if (entry_index < __l0032_dxtable->nentries) {
			entry = &__l0032_dxtable->entry[entry_index];
			if (entry->flags & L0032_DXTABLE_FLAGS_DATAI8TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_READ(int8_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAU8TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_READ(uint8_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAI32TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_READ(int32_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAU32TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_READ(uint32_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAI64TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_READ(int64_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAU64TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_READ(uint64_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAF32TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_READ(float);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAF64TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_READ(double);
			}
		}
	}

	return retval;
}

int l0032_entry_write(entry_handle hentry, int pointno, void* addr) {
	int retval = -1;
	struct l0032_dataxchgtable_entry *entry = NULL;
	int entry_index = L0032_HANDLE2INDEX(hentry);

	// printf("%s: entry index %d\n", __func__, entry_index);
#define __L0032_DATAXCHGTABLE_ENTRY_WRITE(TYPE)	do {\
	TYPE *point = (TYPE*)(((uint8_t*)__l0032_dxtable) + entry->offset + pointno * entry->pointsz);\
	*point = *((TYPE*)addr);\
	retval = sizeof(TYPE);\
	/*printf("w-%s:[%x] val %d\n",  #TYPE, (unsigned int)(entry->offset + pointno * entry->pointsz), (int)*point);*/} while(0)

	if (addr != NULL) {
		if (entry_index < __l0032_dxtable->nentries) {
			entry = &__l0032_dxtable->entry[entry_index];
			if (entry->flags & L0032_DXTABLE_FLAGS_DATAI8TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_WRITE(int8_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAU8TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_WRITE(uint8_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAI32TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_WRITE(int32_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAU32TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_WRITE(uint32_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAI64TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_WRITE(int64_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAU64TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_WRITE(uint64_t);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAF32TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_WRITE(float);
			}
			else if (entry->flags & L0032_DXTABLE_FLAGS_DATAF64TABLE) {
				__L0032_DATAXCHGTABLE_ENTRY_WRITE(double);
			}
		}
	}

	return retval;
}

entry_handle l0032_nextentry(entry_handle hentry)
{
	entry_handle hentry_next = INVALID_ENTRY_HANDLE;
	int entry_index = __l0032_dxtable->nentries;

	l0032_dataxchgtable_lock();
	if (hentry != INVALID_ENTRY_HANDLE) {
		entry_index = L0032_HANDLE2INDEX(hentry);
		if (entry_index + 1 < __l0032_dxtable->nentries) {
			entry_index ++;
			hentry_next = L0032_INDEX2HANDLE(entry_index);
		}
	}

	l0032_dataxchgtable_unlock();
	return hentry_next;
}

entry_handle l0032_get_entry(const char* name)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	int entry_index = 0;
	entry_handle hentry = INVALID_ENTRY_HANDLE;

	l0032_dataxchgtable_lock();
	if (strlen(name) < L0032_DXTABLE_ENTRYNAME_MAX) {
		int i;
		for (i = 0; i < __l0032_dxtable->nentries;i ++) {
			entry = &__l0032_dxtable->entry[i];
			//printf("l0032_dataxchgtable_entry i=%d,%s\n", i, (char*)entry->name);
			if (strlen((char*)entry->name) == strlen(name) && strcmp((char*)entry->name, name) == 0) {
				entry_index = entry - __l0032_dxtable->entry;
				hentry = L0032_INDEX2HANDLE(entry_index);
				//printf("l0032_dataxchgtable_entry name:%s-%s, %d\n",(char*)entry->name, name, entry_index);
				break;
			}
		}
	}
	l0032_dataxchgtable_unlock();
	return hentry;
}

uint32_t l0032_get_nentries(void)
{
	return __l0032_dxtable->nentries;
}

const char* l0032_typestring(int type)
{
	const char* str = "--          ";
	switch (type) {
		case L0032_DXTABLE_FLAGS_UNASSIGNED:
			str = "Not Assigned";
			break;
		case L0032_DXTABLE_FLAGS_DATAI8TABLE:
			str = "Int8        ";
			break;
		case L0032_DXTABLE_FLAGS_DATAU8TABLE:
			str = "UInt8 	   ";
			break;
		case L0032_DXTABLE_FLAGS_DATAU32TABLE:
			str = "Uint32      ";
			break;
		case L0032_DXTABLE_FLAGS_DATAI32TABLE:
			str = "Int32       ";
			break;
		case L0032_DXTABLE_FLAGS_DATAF32TABLE:
			str = "Float       ";
			break;
		case L0032_DXTABLE_FLAGS_DATAF64TABLE:
			str = "Double      ";
			break;
	}

	return str;
}

size_t l0032_typesize(int type)
{
	size_t sz = 0;
	switch (type) {
		case L0032_DXTABLE_FLAGS_DATAI8TABLE:
			sz = sizeof(uint8_t);
			break;
		case L0032_DXTABLE_FLAGS_DATAU8TABLE:
			sz = sizeof(int8_t);
			break;
		case L0032_DXTABLE_FLAGS_DATAU32TABLE:
			sz = sizeof(uint32_t);
			break;
		case L0032_DXTABLE_FLAGS_DATAI32TABLE:
			sz = sizeof(int32_t);
			break;
		case L0032_DXTABLE_FLAGS_DATAF32TABLE:
			sz = sizeof(float);
			break;
		case L0032_DXTABLE_FLAGS_DATAF64TABLE:
			sz = sizeof(double);
			break;
		case L0032_DXTABLE_FLAGS_DATAI64TABLE:
			sz = sizeof(int64_t);
			break;
		case L0032_DXTABLE_FLAGS_DATAU64TABLE:
			sz = sizeof(uint64_t);
			break;
	}

	return sz;
}

const char* l0032_entry_get_name(entry_handle hentry)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	const char *name = NULL;
	int entry_index = L0032_HANDLE2INDEX(hentry);
	l0032_dataxchgtable_lock();
	if (entry_index < __l0032_dxtable->nentries) {
		entry = &__l0032_dxtable->entry[entry_index];
		name = (const char*)entry->name;
	}
	l0032_dataxchgtable_unlock();

	return name;
}

int l0032_entry_get_npoints(entry_handle hentry)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	int npoints = -1;
	int entry_index = L0032_HANDLE2INDEX(hentry);
	l0032_dataxchgtable_lock();
	if (entry_index < __l0032_dxtable->nentries) {
		entry = &__l0032_dxtable->entry[entry_index];
		npoints = entry->npoints;
	}
	l0032_dataxchgtable_unlock();

	return npoints;
}

int l0032_entry_get_pointsz(entry_handle hentry)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	int pointsz = -1;
	int entry_index = L0032_HANDLE2INDEX(hentry);
	l0032_dataxchgtable_lock();
	if (entry_index < __l0032_dxtable->nentries) {
		entry = &__l0032_dxtable->entry[entry_index];
		pointsz = entry->pointsz;
	}
	l0032_dataxchgtable_unlock();

	return pointsz;
}

int l0032_entry_get_offset(entry_handle hentry, uint32_t *offset)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	int retval = -1;
	int entry_index = L0032_HANDLE2INDEX(hentry);
	l0032_dataxchgtable_lock();

	if (entry_index < __l0032_dxtable->nentries) {
		entry = &__l0032_dxtable->entry[entry_index];
		*offset = entry->offset;
		retval = 0;
	}
	l0032_dataxchgtable_unlock();

	return retval;
}

int l0032_entry_get_pointtype(entry_handle hentry)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	int type = -1;
	int entry_index = L0032_HANDLE2INDEX(hentry);

	l0032_dataxchgtable_lock();
	if (entry_index < __l0032_dxtable->nentries) {
		entry = &__l0032_dxtable->entry[entry_index];
		type = entry->flags;
	}
	l0032_dataxchgtable_unlock();

	return type;
}


size_t l0032_entry_get_size(entry_handle hentry)
{
	size_t sz = 0;
	int entry_index = L0032_HANDLE2INDEX(hentry);
	struct l0032_dataxchgtable_entry *entry;

	l0032_dataxchgtable_lock();
	entry = &__l0032_dxtable->entry[entry_index];
	sz = entry->npoints * entry->pointsz;
	l0032_dataxchgtable_unlock();
	
	return sz;
}

/*
* 获取entry在dataxchgtable中的地址和大小
*/
int l0032_entry_get_address(entry_handle hentry, uint8_t **pcache, size_t *sz)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	int retval = -1;
	int entry_index = L0032_HANDLE2INDEX(hentry);
	l0032_dataxchgtable_lock();
	if (entry_index < __l0032_dxtable->nentries && pcache != NULL && sz != NULL) {
		entry = &__l0032_dxtable->entry[entry_index];
		*pcache = ((uint8_t*)__l0032_dxtable) + entry->offset;
		*sz = entry->pointsz * entry->npoints;
		retval = 0;
	}
	l0032_dataxchgtable_unlock();

	return retval;
}

/*
* copy整个dataxchgtable的内容
*/
// int l0032_copy_dataxchgtable(uint8_t **paddr, size_t *sz)
// {
// 	int retval = -1;
// 	if (paddr != NULL && sz != NULL) {
// 		l0032_dataxchgtable_lock();
// 		*sz = __l0032_dxtable->sz;
// 		*paddr = malloc(*sz);
// 		if (*paddr) {
// 			memcpy(*paddr, __l0032_dxtable, *sz);
// 			retval = 0;
// 		}
// 		l0032_dataxchgtable_unlock();
// 	}

// 	return retval;
// }

/*
* copy整个__l0032_dxtable+from开始的所有内容（包括l0032_dataxchgtable的结构体成员变量部分）
*/
int l0032_dataxchgtable_rawcopy(uint8_t **paddr, size_t *sz, uint32_t from)
{
	int retval = -1;
	if (paddr != NULL && sz != NULL) {
		l0032_dataxchgtable_lock();
		if (from + *sz > __l0032_dxtable->sz) {
			*sz = __l0032_dxtable->sz - from;
		}
		*paddr = malloc(*sz);
		if (*paddr) {
			memcpy(*paddr, ((uint8_t*)__l0032_dxtable) + from, *sz);
			retval = 0;
		}
		l0032_dataxchgtable_unlock();
	}

	return retval;
}

int l0032_dataxchgtable_metadata(uint8_t **paddr, size_t *sz)
{
	int retval = -1;
	if (paddr != NULL && sz != NULL) {
		l0032_dataxchgtable_lock();
		*sz = L0032_ALIGN(sizeof(struct l0032_dataxchgtable), 32);
		*paddr = malloc(*sz);
		if (*paddr) {
			memcpy(*paddr, __l0032_dxtable, *sz);
			retval = 0;
		}
		l0032_dataxchgtable_unlock();
	}

	return retval;
}

int l0032_entry_readpoints(entry_handle hentry, int point_from, int *npoints, uint8_t *cache, size_t sz)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	int entry_index = L0032_HANDLE2INDEX(hentry);
	int retval = -1;

	l0032_dataxchgtable_lock();
	if (entry_index < __l0032_dxtable->nentries && cache != NULL && npoints != NULL) {
		entry = &__l0032_dxtable->entry[entry_index];
		if (*npoints == 0) {
			*npoints = entry->npoints;
		}
		if (*npoints + point_from > entry->npoints) {
			*npoints = entry->npoints - point_from;
		}

		if (*npoints * entry->pointsz > sz) {
			*npoints = sz / entry->pointsz;
		}

		if (*npoints > 0) {
			memcpy(cache, ((uint8_t*)__l0032_dxtable) + entry->offset + point_from * entry->pointsz, 
				*npoints * entry->pointsz);
			l0032_dataxchgtable_unlock();
			retval = 0;
		}
	}

	l0032_dataxchgtable_unlock();
	return retval;
}

/*
* 将entry中所有point值置为val
*/

int l0032_entry_writepoints(entry_handle hentry, int point_from, int* npoints, uint8_t *val)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	int entry_index = L0032_HANDLE2INDEX(hentry);
	int retval = -1;

	l0032_dataxchgtable_lock();
	if (entry_index < __l0032_dxtable->nentries && val != NULL && npoints != NULL && *npoints != 0) {
		entry = &__l0032_dxtable->entry[entry_index];
		if (*npoints + point_from > entry->npoints) {
			*npoints = entry->npoints - point_from;
		}

		if (*npoints > 0) {
			memcpy(((uint8_t*)__l0032_dxtable) + entry->offset + point_from * entry->pointsz, val,
				*npoints * entry->pointsz);
			retval = 0;
		}
	}

	l0032_dataxchgtable_unlock();
	return retval;
}

// static struct l0032_dataxchgtable_entry* __l0032_dataxchgtable_get_entrybyname(const char *name)
// {
// 	struct l0032_dataxchgtable_entry *entry = NULL;
// 	int idx;
// 	for (idx = 0; idx < __l0032_dxtable->nentries;idx++) {
// 		struct l0032_dataxchgtable_entry *tmp = &__l0032_dxtable->entry[idx];
// 		if (strlen((char*)tmp->name) == strlen(name) && strcmp((char*)tmp->name, name) == 0) {
// 			entry = tmp;
// 			break;
// 		}
// 	}

// 	return entry;
// }

entry_handle l0032_entry_allocate_buffer(const char* name, size_t sz, int *dxterrno)
{
	entry_handle hentry = l0032_entry_allocate(name, L0032_DXTABLE_FLAGS_DATAU8TABLE, sz, dxterrno);
	if (hentry != INVALID_ENTRY_HANDLE) {
		struct l0032_dataxchgtable_entry* entry;
		entry_handle hentry_kernel = L0032_HANDLE2INDEX(hentry);
		l0032_dataxchgtable_lock();
		if (hentry_kernel < __l0032_dxtable->nentries) {
			entry = &__l0032_dxtable->entry[hentry_kernel];
			entry->flags |= L0032_DXTABLE_FLAGS_DATABUFTABLE;
		}
		l0032_dataxchgtable_unlock();
	}

	return hentry;
}

entry_handle l0032_entry_allocate(const char* name, int type, size_t npoints, int *dxterrno)
{
	struct l0032_dataxchgtable_entry *entry = NULL;
	size_t pointsz = l0032_typesize(type);
	entry_handle hentry = INVALID_ENTRY_HANDLE;
	int _errno = L0032_DXTABLE_ERRNO_NOERROR;

	if (pointsz == 0) {
		goto out;
	}
	if ((hentry = l0032_get_entry(name)) != INVALID_ENTRY_HANDLE) {
		//printf("dataxchgtable_allocateentry already find= %s\n", name);
		size_t len;
		int entry_index = -1;
		l0032_dataxchgtable_lock();
		entry_index = L0032_HANDLE2INDEX(hentry);
		entry = &__l0032_dxtable->entry[entry_index];
		len = entry->npoints * entry->pointsz;
		if (pointsz * npoints <= len) {
			// memset(((uint8_t*)__l0032_dxtable) + entry->offset, 0x0, len);
			;
		}
		else {
			// entry existed, but the new requested size is bigger.
			hentry = INVALID_ENTRY_HANDLE;
			_errno = L0032_DXTABLE_ERRNO_SIZE;
		}
		l0032_dataxchgtable_unlock();
		//printf("exist-entry name:%s, entryidx:%d, entrysz:%d \n", name, idx, len);
		
		goto out;
	}
	l0032_dataxchgtable_lock();
	if (__l0032_dxtable->nentries < L0032_DXTABLE_ENTRYMAX && strlen(name) < L0032_DXTABLE_ENTRYNAME_MAX) {
		int i;
		size_t sz;
		for (i = 0; i < __l0032_dxtable->nentries;i ++) {
			entry = &__l0032_dxtable->entry[i];
			//printf("[%02d]=%0x, offset:%d, pointsz:%d, points:%d, datatype:%d, name:%s,  \n", i,L0032_INDEX2HANDLE(i),entry->offset,
			//	entry->pointsz, entry->npoints,entry->flags, entry->name);
			if (entry->flags != L0032_DXTABLE_FLAGS_UNASSIGNED && strlen((char*)entry->name) == strlen(name) && strcmp((char*)entry->name, name) == 0) {
				goto outunlock;				
			}
		}
		entry = &__l0032_dxtable->entry[__l0032_dxtable->nentries];
		sz = npoints * pointsz;
		entry->flags = type;
		// printf("%zu %u %u\n", sz, __l0032_dxtable->offset_data, __l0032_dxtable->end);
		if (sz + __l0032_dxtable->offset_data < __l0032_dxtable->end) {
			struct l0032_dataxchgtable_entry *entry_last = NULL;
			memcpy(entry->name, name, strlen(name));
			entry->offset = __l0032_dxtable->offset_data;
			entry->npoints = npoints;
			entry->pointsz = pointsz;
			for (i = 0; i < __l0032_dxtable->nentries;i ++) {
				if (__l0032_dxtable->entry[i].flags == type) {
					entry_last = &__l0032_dxtable->entry[i];
				}
			}
			if (entry_last) {
				entry_last->next = entry - &__l0032_dxtable->entry[0];
			}

			memset(((uint8_t*)__l0032_dxtable)+__l0032_dxtable->offset_data, 0x0, sz);
			
			__l0032_dxtable->nentries ++;
			__l0032_dxtable->offset_data += sz;
			
			hentry = L0032_INDEX2HANDLE(entry - __l0032_dxtable->entry);

		}

		//printf("create-entry name:%s,idx:%d, points:%lu, pointsz:%lu, sz:%lu, dxt-offset:%u, hentry:%0x\n", name,
		//	__l0032_dxtable->nentries-1, npoints, pointsz, sz, __l0032_dxtable->offset_data, hentry);
outunlock:
		l0032_dataxchgtable_unlock();
	}
out:
	if (dxterrno != NULL) {
		*dxterrno = _errno;
	}
	return hentry;
}
